<template>
  <span>
    <!-- 正常列 -->
    <template v-for="col in columnConfig">
      <multi-header-column
        v-if="col.children && col.children.length"
        :key="col.prop"
        :col="col"
        :align="col.align || parentOption.align || config.align"
        :header-align="col.headerAlign || parentOption.headerAlign || config.headerAlign"
      />
      <el-table-column
        v-else-if="!col.hide"
        :show-overflow-tooltip="vaildBoolean(col.showOverflowTooltip,true)"
        :key="col.prop"
        :prop="col.prop"
        :label="col.label"
        :width="col.width"
        :min-width="col.minWidth"
        :fixed="col.fixed"
        :sortable="col.sortable || false"
        :align="col.align || parentOption.align || config.align"
        :header-align="col.headerAlign || parentOption.headerAlign || config.headerAlign"
        :render-header="col.renderHeader"
        :filters="_handleFilters(col)"
        :filter-method="col.filter? _handleFiltersMethod : undefined"
        :filter-multiple="vaildBoolean(col.filterMultiple,true)"
        filter-placement="bottom-end"
      >
        <template v-if="col.headerSlot" slot="header">
          <slot :name="`${col.prop}Header`" :column="col"/>
        </template>
        <template slot-scope="{ row ,column}">
          <slot
            v-if="col.slot"
            :name="col.prop"
            :value="getValueByPath(row, col.prop)"
            :label="handleDetail(row,col,DIC[col.prop])"
            :scopeRow="scopeRow"
            :row="row"
            :size="controlSize"
            :column="col"
            :readonly="col.readonly"
            :clearable="vaildBoolean(col.clearable,true)"
            :disabled="vaildBoolean(col.disabled,row.$btnDisabled)"
            :isEdit="cellEditFlag(row,col)"
            :dic="DIC[col.prop]"
          />

          <form-temp
            v-else-if="cellEditFlag(row,col)"
            :value="getValueByPath(row, col.prop)"
            :is-crud="true"
            :column="delete col.width ? col : col"
            :size="controlSize"
            :dic="DIC[col.prop]"
            :upload-before="col.uploadBefore"
            :upload-after="col.uploadAfter"
            :readonly="col.readonly"
            :clearable="vaildBoolean(col.clearable,true)"
            :disabled="vaildBoolean(col.disabled,row.$btnDisabled)"
            :text-mode="col.textMode"
            @click.native.stop
            @input="modelInput($event,row,col)"
          />
          <template v-else>
            <span v-if="['array'].includes(col.type)">{{ _detailData(row,col) }}</span>
            <span v-else-if="['url'].includes(col.type)">
              <el-link
                v-bind="!!col.click ? '' :{
                  href: getValueByPath(scopeRow.row, col.prop),
                  target:col.target || '_blank'
                }"
                type="primary"
                @click="col.click(getValueByPath(row, col.prop),row,col)"
              >{{ getValueByPath(row, col.prop) }}</el-link>
            </span>
            <span v-else-if="col.displayAs=='switch' && ['switch'].includes(col.type)">
              <z-switch
                :size="controlSize"
                :value="getValueByPath(row, col.prop)"
                :active-color="col.activeColor"
                :inactive-color="col.inactiveColor"
                disabled
              />
            </span>
            <span v-else-if="['img'].includes(col.type)">
              <z-img
                :value="getValueByPath(row, col.prop)"
                :load="col.load"
                :error="col.error"
              >
                <!-- <template #placeholder="scope">
                  <slot :name="`${col.prop}Placeholder`" :scope="scope"></slot>
                </template>
                <template #error="scope">
                  <slot :name="`${col.prop}Error`" :scope="scope"></slot>
                </template>-->
              </z-img>
            </span>
            <span v-else v-html="_columnFormatter(row,column,col)"/>

          </template>
        </template>
      </el-table-column>
    </template>
  </span>
</template>
<script>
import { detail } from '../utils/detail'
import { validatenull } from '../utils/validate'
import { deepClone, vaildBoolean, getValueByPath, getPropByPath } from '../utils/util'
import formTemp from '../formtemp'
import { DIC_PROPS, DIC_SPLIT, EMPTY_VALUE } from '../global/variable'
import multiHeaderColumn from './multiHeaderColumn'
import zImg from './z-img'

export default {
  name: 'Column',
  inject: ['crud'],
  provide() {
    return {
      multiColumn: this
    }
  },
  components: { formTemp, multiHeaderColumn, zImg },
  props: {
    columnConfig: {
      type: Array,
      required: true,
      default: () => []
    }
  },
  data() {
    return {
      DIC: this.crud.DIC,
      config: this.crud.config,
      controlSize: this.crud.controlSize,
      parentOption: this.crud.parentOption,
      tableOption: this.crud.tableOption
    }
  },
  methods: {
    vaildBoolean,
    validatenull,
    getValueByPath,
    getPropByPath,
    cellEditFlag(row, column) {
      // && column.slot !== true
      console.log('isEdit', row, column, row.$cellEdit && column.cell)
      return !!(row.$cellEdit && column.cell)
    },
    _detailData( row , col) {
      const { prop, dataType, props: { label }} = col
      const list = this.getValueByPath(row, prop)
      let res = EMPTY_VALUE

      if (!Array.isArray(list) && ['string', 'number'].includes(dataType)) {
        res = list.split(',').join(' | ')
      } else if (Array.isArray(list) && list.length) {
        res = list.map(item => item[label]).join(' | ')
      }

      return res
    },
    // 由于slot-scope和formatter不能共存只能如此
    _columnFormatter(scopeRow, column, currentColumn) {
      const row = scopeRow

      if (typeof currentColumn.formatter === 'function') {
        return currentColumn.formatter(row, this.getValueByPath(row, currentColumn.prop), currentColumn.label, currentColumn)
      } else {
        return this._globalColumnFormatter(row, column, currentColumn)
      }
    },
    // 全局初始化
    _globalColumnFormatter(row, column, currentColumn) {
      const value = this.getValueByPath(row, column.property)

      if (this.validatenull(value)) {
        return EMPTY_VALUE
      }
      return this.handleDetail(
        row,
        currentColumn,
        this.DIC[currentColumn.prop]
      )
    },
    handleDetail(row, column, DIC) {
      let result = this.getValueByPath(row, column.prop)

      if (typeof column.type === 'undefined') return result
      // 如果是级联，切值为字符串，则需要对值进行处理
      if (column.type === 'cascader' && typeof result === 'string') {
        const list = result.split(',')
        if (list.length > 1) {
          row = deepClone(row)
          row[column.prop] = list
        }
      }
      // 进行取值处理，取出对应的label值
      result = detail(row, column, this.tableOption, DIC)
      if (!this.validatenull(DIC)) {
        row['$' + column.prop] = result
      }
      // 如果是级联，则对结果进行处理
      if (column.type === 'cascader') {
        const { prop, props, presentText, showAllLevels } = column
        // 如果开启了elementUI级联的lazy模式，则从column.presentText中读值，此值在cascader的mounted中赋值
        if (props && props.lazy) {
          result = presentText
          row['$' + prop] = presentText
        }
        if (showAllLevels === false && typeof result === 'string') {
          const list = result.split(DIC_SPLIT)
          result = list[list.length - 1]
        }
      }
      return result
    },
    modelInput(value, model, { type, prop }) {
      const parentObj = this.getPropByPath(model, prop).o
      parentObj[prop.split('.').pop()] = value
    },
    // 表格筛选逻辑
    _handleFiltersMethod(value, row, column) {
      const columnNew = this.columnConfig.filter(
        ele => ele.prop === column.property
      )[0]
      if (typeof columnNew.filtersMethod === 'function') {
        return columnNew.filtersMethod(value, row, columnNew)
      } else {
        return row[columnNew.prop] === value
      }
    },
    // 表格筛选字典
    _handleFilters(column) {
      if (column.filter !== true) return undefined
      if (this.validatenull(column.dicFilters)) {
        const list = [];
        (this.DIC[column.prop] || []).forEach(ele => {
          const props = column.props || this.tableOption.props || {}
          list.push({
            text: ele[props.label || DIC_PROPS.label],
            value: ele[props.value || DIC_PROPS.value]
          })
        })
        return list
      }
      return column.dicFilters
    }
  }
}
</script>
